#include "VideoDecoder.h"

VideoDecoder::VideoDecoder(QObject *parent) : QObject(parent)
{
    m_codec = (AVCodec*)avcodec_find_decoder(AV_CODEC_ID_H264);
    if (!m_codec) {
        qWarning("H.264 decoder not found");
        return;
    }

    m_codecContext = avcodec_alloc_context3(m_codec);
    if (!m_codecContext) {
        qWarning("Could not allocate video codec context");
        return;
    }

    if (avcodec_open2(m_codecContext, m_codec, nullptr) < 0) {
        qWarning("Could not open codec");
        return;
    }

    m_parser = av_parser_init(AV_CODEC_ID_H264);
    if (!m_parser) {
        qWarning("Could not initialize parser");
        return;
    }

    m_frame = av_frame_alloc();
    if (!m_frame) {
        qWarning("Could not allocate video frame");
        return;
    }

    m_initialized = true;
}

VideoDecoder::~VideoDecoder()
{
    stop();
    cleanup();
}

void VideoDecoder::cleanup()
{
    if (m_parser) {
        av_parser_close(m_parser);
        m_parser = nullptr;
    }
    if (m_codecContext) {
        avcodec_close(m_codecContext);
        avcodec_free_context(&m_codecContext);
        m_codecContext = nullptr;
    }
    if (m_frame) {
        av_frame_free(&m_frame);
        m_frame = nullptr;
    }
    if (m_swsContext) {
        sws_freeContext(m_swsContext);
        m_swsContext = nullptr;
    }
}

void VideoDecoder::stop()
{
    QMutexLocker locker(&m_mutex);
    m_running = false;
}

void VideoDecoder::enqueueData(const QByteArray &data)
{
    QMutexLocker locker(&m_mutex);
    if (m_running) {
        m_dataQueue.enqueue(data);
    }
}

void VideoDecoder::decode(const QByteArray &data)
{
    AVPacket packet;
    av_init_packet(&packet);
    packet.data = (uint8_t*)data.data();
    packet.size = data.size();

    int ret = avcodec_send_packet(m_codecContext, &packet);
    if (ret < 0) {
        qWarning("Error sending a packet for decoding");
        return;
    }

    while (ret >= 0) {
        ret = avcodec_receive_frame(m_codecContext, m_frame);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
            return;
        } else if (ret < 0) {
            qWarning("Error during decoding");
            return;
        }

        // 设置图像转换上下文
        if (!m_swsContext) {
            m_swsContext = sws_getContext(m_frame->width, m_frame->height,
                                          (AVPixelFormat)m_frame->format,
                                          m_frame->width, m_frame->height,
                                          AV_PIX_FMT_RGB32,
                                          SWS_BILINEAR, nullptr, nullptr, nullptr);
            if (!m_swsContext) {
                qWarning("Could not initialize the conversion context");
                return;
            }
        }

        // 创建QImage并转换格式
        QImage image(m_frame->width, m_frame->height, QImage::Format_RGB32);
        uint8_t *dest[4] = { image.bits(), nullptr, nullptr, nullptr };
        int dest_linesize[4] = { static_cast<int>(image.bytesPerLine()), 0, 0, 0 };

        sws_scale(m_swsContext, m_frame->data, m_frame->linesize, 0,
                  m_frame->height, dest, dest_linesize);

        emit frameDecoded(image);
    }
}
